﻿using System;
using System.Activities;
using System.Activities.Statements;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.TeamFoundation.Build.Client;
using System.Globalization;
using TfsExtensions.Build.ActivityLibrary.Tests;
using TfsExtensions.Build.Activities.Entities;
using System.Collections.ObjectModel;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Client;

namespace TfsExtensions.Build.Activities.Tests
{
    /// <summary>
    /// Tests to verify the functionality of the UpdateVersionInfo activity
    /// </summary>
    [TestClass]
    public class UpdateVersionInfoTest
    {
        #region Housekeeping
        /// <summary>
        /// Default constructor
        /// </summary>
        public UpdateVersionInfoTest()
        {
        }


        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
       
        #endregion

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        #region Test Methods

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateAssemblyTestWithInvalidFileExtension()
        {
            List<Tuple<String, String>> resourceFiles = new List<Tuple<String, String>>() {
                new Tuple<String, String>("AssemblyInfo.cpp", MetadataUpdaterResources.AssemblyInfo_cpp),
            };

            Collection<string> fullPathtoFiles = new Collection<string>();

            foreach (Tuple<String, String> tuple in resourceFiles)
            {
                var path = Path.Combine(Path.GetTempPath(), tuple.Item1);
                fullPathtoFiles.Add(path);
                using (StreamWriter writer = File.CreateText(path))
                {
                    writer.Write(tuple.Item2);
                    writer.Flush();
                    writer.Close();
                }
            }

            IDictionary<String, Object> inputs = new Dictionary<string, object>();
            inputs.Add("AssemblyInfoFiles", fullPathtoFiles);
            inputs.Add("AssemblyMetadataSettings", GetRulesObject());

            WorkflowInvoker.Invoke(new UpdateAssemblyInfo(), inputs);

        }

        private bool VerifyFileContent(string filepath, string content)
        {
            string contents = "";
            using (FileStream fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.None))
            {
                using (StreamReader streamReader = new StreamReader(fileStream))
                {
                    contents = streamReader.ReadToEnd();

                }
            }
            return contents.Contains(content);
        }
        [TestMethod]
        public void UpdateAssemblyTestWithValidFileExtension()
        {
            List<Tuple<String, String>> resourceFiles = new List<Tuple<String, String>>() {
                new Tuple<String, String>("AssemblyInfo.cs", MetadataUpdaterResources.AssemblyInfo_cs),
                new Tuple<String, String>("AssemblyInfo.vb", MetadataUpdaterResources.AssemblyInfo_vb),
            };

            Collection<string> fullPathtoFiles = new Collection<string>();

            foreach (Tuple<String, String> tuple in resourceFiles)
            {
                var path = Path.Combine(Path.GetTempPath(), tuple.Item1);
                fullPathtoFiles.Add(path);
                using (StreamWriter writer = File.CreateText(path))
                {
                    writer.Write(tuple.Item2);
                    writer.Flush();
                    writer.Close();
                }
            }

            IDictionary<String, Object> inputs = new Dictionary<string, object>();
            inputs.Add("AssemblyInfoFiles", fullPathtoFiles);
            inputs.Add("AssemblyMetadataSettings", GetRulesObject());

            WorkflowInvoker.Invoke(new UpdateAssemblyInfo(), inputs);

            // Verify 
            bool result = VerifyFileContent(fullPathtoFiles[0], "Test Application Name");
            Assert.AreEqual(result, true);
            result = VerifyFileContent(fullPathtoFiles[1], "1.1.1.1");
            Assert.AreEqual(result, false);

            result = VerifyFileContent(fullPathtoFiles[0], "1.2.2.2");
            Assert.AreEqual(result, false);
        }

        [TestMethod]
        public void UpdateProjectTest()
        {
            List<Tuple<String, String>> resourceFiles = new List<Tuple<String, String>>() {
                new Tuple<String, String>("CSProject.csproj", MetadataUpdaterResources.CSProject),
                new Tuple<String, String>("VBProject.vbproj", MetadataUpdaterResources.VBProject),
            };

            Collection<string> fullPathtoFiles = new Collection<string>();

            foreach (Tuple<String, String> tuple in resourceFiles)
            {
                var path = Path.Combine(Path.GetTempPath(), tuple.Item1);
                fullPathtoFiles.Add(path);
                using (StreamWriter writer = File.CreateText(path))
                {
                    writer.Write(tuple.Item2);
                    writer.Flush();
                    writer.Close();
                }
            }

            IDictionary<String, Object> inputs = new Dictionary<string, object>();
            inputs.Add("ProjectFilesToProcess", fullPathtoFiles);
            inputs.Add("AssemblyMetadataSettings", GetRulesObject());

            WorkflowInvoker.Invoke(new UpdateProject(), inputs);

            // Verify 
            bool result = VerifyFileContent(fullPathtoFiles[0], "MyKeyContainer");
            Assert.AreEqual(result, true);
            result = VerifyFileContent(fullPathtoFiles[1], "<SignAssembly>");
            Assert.AreEqual(result, true);
            result = VerifyFileContent(fullPathtoFiles[1], "<DelaySign>false</DelaySign>");
            Assert.AreEqual(result, false);

        }

        [TestMethod]
        public void UpdateSolutionTest()
        {
            List<Tuple<String, String>> resourceFiles = new List<Tuple<String, String>>() {
                new Tuple<String, String>("WebSite.sln",System.Text.ASCIIEncoding.ASCII.GetString(MetadataUpdaterResources.WebSite)),
            };

            Collection<string> fullPathtoFiles = new Collection<string>();

            foreach (Tuple<String, String> tuple in resourceFiles)
            {
                var path = Path.Combine(Path.GetTempPath(), tuple.Item1);
                fullPathtoFiles.Add(path);
                using (StreamWriter writer = File.CreateText(path))
                {
                    writer.Write(tuple.Item2);
                    writer.Flush();
                    writer.Close();
                }
            }

            IDictionary<String, Object> inputs = new Dictionary<string, object>();
            inputs.Add("SolutionFilesToProcess", fullPathtoFiles);
            inputs.Add("AssemblyMetadataSettings", GetRulesObject());

            WorkflowInvoker.Invoke(new UpdateSolution(), inputs);

            // Verify 
            bool result = VerifyFileContent(fullPathtoFiles[0], "MyKeyContainer");
            Assert.AreEqual(result, true);
            result = VerifyFileContent(fullPathtoFiles[0], "MyKeyContainer1");
            Assert.AreEqual(result, false);
        }

        private AssemblySettings GetRulesObject()
        {
            AssemblySettings settings = new AssemblySettings();
            settings.AssemblyMetadataDetails = new AssemblyApplicationSettings
            {
                ApplicationName = "Test Application Name",
                ApplicationDescription = "Test Application Description",
                CompanyName = "Test Company Description",
                IsAssemblyMetadataSelected = true
            };

            settings.AssemblyVersionDetails = new AssemblyVersionSettings()
            {
                Major = "2",
                Minor = "2",
                Build = "2",
                Revision = "2",
                IsAssemblyVersionSelected = true
            };

            settings.FileVersionDetails = new AssemblyFileVersionSettings()
            {
                Major = "2",
                Minor = "2",
                IsFileVersionSelected = true
            };

            settings.AssemblySigningDetails = new AssemblySigningSettings()
            {
                IsDelaySigned = true,
                StrongKeyName = "MyKeyContainer",
                IsAssemblySigning = true,
                StrongKeyFilePath = Path.GetTempPath()

            };

            return settings;
        }

        #endregion
    }
}
